package com.weiun.common.core.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.alibaba.fastjson.JSONObject;
import com.weiun.common.base.bean.ParamBean;
import com.weiun.common.base.bean.ResultBean;
import com.weiun.common.base.exception.BizMsgException;
import com.weiun.common.core.tool.SpringContext;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * The type Base api controller.
 *
 * @author yaocai
 */
public class BaseApiController extends BaseController {

    private final Log log = LogFactory.get();

    public final static String API_PARAM = "ApiParam";

    /**
     * [PV][{ip}:{service}/{method}]{param}
     */
    private final String PV = "[PV][{}:{}/{}]{}";


    @ResponseBody
    @RequestMapping(value = "/api/{service}/{method}", method = RequestMethod.POST, consumes = "application/json")
    public ResultBean api(HttpServletRequest request, @PathVariable String service, @PathVariable String method,
                          @RequestBody() JSONObject param) throws Exception {
        ParamBean paramBean = getParamBean(request);
        paramBean.setService(service);
        paramBean.setMethod(method);
        paramBean.setParam(param);
        if (checkSign()) {
            checkParam(paramBean);
        }
        request.setAttribute(API_PARAM, paramBean);
        ResultBean resultBean = serviceInvoke(paramBean);
        return resultBean;
    }

    /**
     * Check sign boolean.
     * 是否需要进行签名检验
     *
     * @return the boolean
     */
    protected boolean checkSign() {
        return true;
    }

    private ResultBean serviceInvoke(ParamBean paramBean) throws Exception {
        // 服务调用
        Object service = null;
        try {
            service = SpringContext.getBean(paramBean.getService());
        } catch (Exception e) {
        }
        if (service == null) {
            service = SpringContext.getBean(paramBean.getService() + "Impl");
        }
        if (service == null) {
            throw new BizMsgException(StrUtil.format("No {} service.", paramBean.getService()));
        }
        Method method = null;
        try {
            method = service.getClass().getMethod(paramBean.getMethod().trim(), ParamBean.class);
        } catch (Exception e) {
            throw new BizMsgException(StrUtil.format("No {} method in {} service", paramBean.getMethod(), paramBean.getService()));
        }
        if (method == null) {
            throw new BizMsgException(StrUtil.format("No {} method in {} service", paramBean.getMethod(), paramBean.getService()));
        }
        ResultBean result = (ResultBean) method.invoke(service, paramBean);
        log.info(PV, paramBean.getIp(), paramBean.getService(), paramBean.getMethod(), paramBean.toString());
        return result;
    }

}
